package com.koomii.common.util.bean;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;

/**
 * User:
 * Date: 2010-5-7
 * Time: 14:00:11
 */
public class BeanUtils {

    private static BeanUtils instance;

    private final static String GET_METHOD = "get";

    private BeanUtils(){}

    public static BeanUtils getInstance(){
        if( null == instance ){
            synchronized(GET_METHOD){
                instance = new BeanUtils();
            }
        }
        return instance;
    }

    /**
     * @param
     * @return
     */
    public BeanUtils  beanToMap(Map map,Object obj,String prefix) {
        if (null == obj ) {
            return this;
        }
        Class c = obj.getClass();
        Class cc = c.getSuperclass();
        Field[] fieldArr = c.getDeclaredFields();
        for (Field field : fieldArr) {
            pushField(obj, map, c, field,prefix);
        }
        fieldArr = cc.getDeclaredFields();
        for (Field field : fieldArr) {
            pushField(obj, map, cc, field,prefix);
        }
        return this;
    }

    private void pushField(Object obj, Map map, Class c, Field field,String prefix) {
        int i = field.getModifiers();
        if (vevifField(obj, map, field, i,prefix)){
            return;
        }
        Object retObj = null;
        try {
            String stringLetter = field.getName().substring(0, 1).toUpperCase();
            String getMethodName = GET_METHOD + stringLetter + field.getName().substring(1);
            Method getMethod = c.getMethod(getMethodName, new Class[]{});
            retObj = getMethod.invoke(obj, new Object[]{});
        } catch (Exception e) {
            retObj = null;
        }
        if (null ==retObj && Modifier.isPublic(i)) {
            try {
                retObj = field.get(obj);
            } catch (Exception e) {
                retObj = null;
            }
        }
        pushMap(map, field.getName(), retObj,prefix);
    }

    private boolean vevifField(Object obj, Map map, Field field, int i,String prefix) {
        FieldTransient ft = field.getAnnotation(FieldTransient.class);
        if (null != ft) {
            return true;
        }
        if (Modifier.isAbstract(i) || Modifier.isInterface(i) || Modifier.isTransient(i)) {
            return true;
    }
        if (Modifier.isPublic(i) && Modifier.isStatic(i)) {
            try {
                Object retObj = field.get(obj);
                pushMap(map, field.getName(), retObj,prefix);
            } catch (Exception e) {
            }
            return true;
        }
        return false;
    }

    private Map pushMap(Map map, Object key, Object value,String prefix) {
        if (null != key && null != value) {
            map.put(prefix+key, value);
        }
        return map;
    }

}
